package com.example.competitionregistration.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.competitionregistration.common.ErrorCode;
import com.example.competitionregistration.common.Result;
import com.example.competitionregistration.entity.Attachement;
import com.example.competitionregistration.mapper.AttachementMapper;
import com.example.competitionregistration.service.AttachementService;
import jakarta.annotation.Resource;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
 * @Author ZhangJun
 * @Description 由赛事发布者上传，供访客下载的文件的服务类实现
 * @Date 2023/7/11
 **/
@Service
public class AttachementServiceImpl implements AttachementService {
    @Resource
    private AttachementMapper attachementMapper;
    @Value("${file.uploadPath}")
    private String uploadPath;

    /**
     * @param userId 请求上传文件的用户id
     * @param file   请求上传的文件
     * @return 上传结果
     * @Author ZhangJun
     * @Description 上传文件的内部实现
     * @Date 2023/7/11 14:50
     **/
    @Override
    public Result uploadFile(String userId, MultipartFile file) {
        // TODO: if user not exist then throw new FileUploadException("指定的用户不存在")
        // or let's just trust it...?
        Attachement attachement = new Attachement();
        attachement.setUploaderId(userId);
        attachement.setFileName(file.getOriginalFilename());
        attachement.setUploadTime(LocalDateTime.now().atOffset(ZoneOffset.of("+8")));
        attachement.setStoragePaths(attachement.getUploaderId());
        //attachement.setUploaderType(?);
        if (attachementMapper.insert(attachement) != 1)
            return Result.error(ErrorCode.FILE_UPLOAD_FAILURE_ERROR.getCode(), ErrorCode.FILE_UPLOAD_FAILURE_ERROR.getMsg());
        try {
            File destDir = new File(String.format("%s/%s", uploadPath, attachement.getStoragePaths()));
            if (!destDir.exists()) destDir.mkdirs();
            file.transferTo(Path.of(String.format("%s/%s", destDir.getCanonicalPath(), attachement.getId())));
        } catch (IOException e) {
            e.printStackTrace();
            return Result.error(ErrorCode.FILE_UPLOAD_FAILURE_ERROR.getCode(), ErrorCode.FILE_UPLOAD_FAILURE_ERROR.getMsg());
        }
        return Result.success();
    }

    /**
     * @param fileUuid 请求下载的文件的UUID
     * @return 请求下载的文件
     * @Author ZhangJun
     * @Description 下载文件时从数据库获取文件信息的方法
     * @Date 2023/7/14 12:04
     **/
    @Override
    public Result getFile(String fileUuid) {
        if (!StringUtils.hasText(fileUuid))
            return Result.error(ErrorCode.FILE_NOT_FOUND_ERROR.getCode(), ErrorCode.FILE_NOT_FOUND_ERROR.getMsg());
        try {
            Attachement queryResult = attachementMapper.selectOne(new QueryWrapper<Attachement>().eq("id", fileUuid));
            if (queryResult == null)
                return Result.error(ErrorCode.FILE_NOT_FOUND_ERROR.getCode(), ErrorCode.FILE_NOT_FOUND_ERROR.getMsg());
            return Result.success(queryResult);
        } catch (TooManyResultsException e) {
            LoggerFactory.getLogger(AttachementServiceImpl.class).error("用户请求的文件UUID在数据库中出现重复：" + fileUuid);
            return Result.error(ErrorCode.FILE_NOT_FOUND_ERROR.getCode(), ErrorCode.FILE_NOT_FOUND_ERROR.getMsg());
        }
    }

    /**
     * @param file 从数据库取回的请求下载的文件实体
     * @return 文件在服务器中的实际储存路径
     * @Author ZhangJun
     * @Description 获取文件在服务器中的实际储存路径，约定为 （配置文件中的）上传根目录/（storage_paths字段记录的）文件储存路径/（id字段记录的）文件UUID
     * @Date 2023/7/14 13:42
     **/
    @Override
    public String getActualPath(Attachement file) {
        return String.format("%s/%s/%s", uploadPath, file.getStoragePaths(), file.getId());
    }
}
